

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <setjmp.h>

/* add your code here */

/* mythread_t - typedef integer that represents the thread id */
typedef int mythread_t;

/* mythread_attr_t - typedef integer that represents the new thread's stack size */
typedef unsigned int mythread_attr_t;

/* Node pointer typedef that is used to point to the next and previous pointers */
typedef struct node *nodeptr;

/**
 * Node type for doubly linked list 
 * each entry has a pointer to previous
 * node in the list, and next node in the list
 *
 * Each of these node_t structures represents a TCB
 */
typedef struct node {
    mythread_t threadId;  /* the id of this thread */
	int status;   /* the status of the thread: ready = 0, blocked = 1, terminated = 2 */
	int initFlag;  /* Indicates whether or not the thread has been run before or not: hasn't run = 0, has run = 1 */
	mythread_t blockedFor; /* id of target thread that this thread is blocked for */
	int returnedStatus; /* the status returned by this thread upon execution */
	jmp_buf currentContext; /* saved execution context of this thread*/
	void *funcAddress;  /* Address of the function to call for this thread */
	void *funcArg;  /* Address of argument to be passed to this function */
    nodeptr next; /* the next node in the list */
    nodeptr  prev; /*the previous node in the list */
} node_t;

/**
 * Prints the contents of the queue (each thread's ID), used for queue testing purposes
 *
 */
void printQueue();

/**
 * mythread_self -  returns thread id of running thread
 *
 *  \return thread ID of the currently executing thread
 */
mythread_t mythread_self(void);

/**
 * mythread_create - prepares context of new_thread_ID as start_func(arg),
 * attr is ignored right now.
 *
 * \param id of the new thread
 * \param attribute that indicates a user-defined stack size
 * \param pointer to the function that should be called when thread is created
 * \param pointer to any argument to the function requires
 * \return integer that indicates successful return of mythread_create function, 0 indicates success
 */
int mythread_create(mythread_t *new_thread_ID,
					mythread_attr_t *attr,
					void * (*start_func)(void *),
					void *arg);

/**
 * mythread_yield - switch from running thread to the next ready one
 *
 * \return integer that indicates if the yield succeeded
 */
int mythread_yield(void);

/**
 * mythread_join - suspend calling thread if target_thread has not finished,
 * enqueue on the join Q of the target thread, then dispatch ready thread;
 * once target_thread finishes, it activates the calling thread / marks it
 * as ready.
 *
 * \param id of the target thread to wait on
 * \param return status of the target thread
 * \return integer flag that indicates if the join succeeded: 0 for success, 1 for failure
 */
int mythread_join(mythread_t target_thread, void **status);

/**
 * mythread_exit - exit thread, awakes joiners on return
 * from thread_func and dequeue itself from run Q before dispatching run->next
 *
 * \param return value, indicates success (0) or failure (1)
 */
void mythread_exit(void *retval);

#endif /* MYTHREAD_H */
